home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
vbccwossrc.lha
/
vbcc
/
pasm
/
eval.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-07
|
22KB
|
828 lines
/* $VER: pasm eval.c V1.2 (21.10.98)
*
* This file is part of pasm, a portable PowerPC assembler.
* Copyright (c) 1997-98 Frank Wille
*
* pasm is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
* pasm may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v1.2 (21.10.98) phx
* @sdarx and @sdax are recognized and generate a R_PPC_SDAREL16
* relocation.
* Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
* v1.1e (19.10.98) phx
* Improved hihalf(): >> instead /
* v1.0 (04.04.98) phx
* ADDR16-relocation/xref works for instructions, like addi, cmpi, etc.
* v0.9 (07.03.98) phx
* The EHF-offset for R_REL14 is handled in instructions.c. No need
* to increase the return value in makexref() and makereloc().
* v0.7 (01.01.98) phx
* @ha, @h, @l are only allowed at the end of an operand, according
* to GNU-as notation. '@' is only allowed as the first character in
* a symbol (for @function and @object, for example).
* Don't waste memory in makereloc() and makexref() by adding new
* nodes to the current section if another pass is required
* anyway.
* v0.5 (11.10.97) phx
* getarg() works with \' and \" now.
* v0.4 (05.07.97) phx
* R_PPC_TOC16 and R_PPC_REL14 support in makereloc() and makexref().
* "(<term>)@l/h/ha" was not recognized.
* A comment introducer '#' was erroneously treated as a macro
* parameter in read_macro_params().
* Undefined symbols are only automatically declared as externally
* defined, if the -x option was given. Otherwise display an
* error message.
* Implementing backwards-evaluation of an expression in v0.3 was not
* very smart (e.g. 4-1+2 => 1(!)) - changed to forward again... ;)
* v0.3 (20.04.97) phx
* Bug in eval_expression() fixed, which sometimes caused the loss
* of the last argument of an expression.
* v0.2 (25.03.97) phx
* Writes ELF object for 32-bit PowerPC big-endian. Either absolute
* or ELF output format may be selected. ELF is default for all
* currently supported platforms. PPCasm supports nine different
* relocation types (there are much more...).
* Compiles and works also under NetBSD/amiga (68k).
* Changed function declaration to 'new style' in all sources
* (to avoid problems with '...' for example).
* makexref() and makereloc() used wrong offset.
* v0.1 (11.03.97) phx
* First test version with all PowerPC instructions and most
* important directives. Only raw, absolute output.
* v0.0 (21.02.97) phx
* File created.
*/
#define EVAL_C
#include "ppcasm.h"
char *getsymbol(struct GlobalVars *,char *);
char *getarg(struct GlobalVars *,char *);
char *skipspaces(char *);
char *remquotes(char *);
void checkEOL(char *);
char *skipexpression(struct GlobalVars *,char *);
void read_macro_params(struct GlobalVars *,struct ParsedLine *,
struct MacroParams *,char *);
char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
uint32 makereloc(struct GlobalVars *,struct Expression *);
uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
char *getintexp(struct GlobalVars *,char *,uint32 *);
char *eval_expression(struct GlobalVars *,struct Expression *,char *);
static uint32 hihalf(struct GlobalVars *,uint32);
static uint32 lohalf(struct GlobalVars *,uint32);
static uint32 read_hex(char *);
static uint32 read_dec(char *);
static uint32 read_oct(char *);
static uint32 read_bin(char *);
static uint32 read_str(char *);
/* table of valid symbol characters,
0=invalid, 1=valid in whole symbol, 2=valid, but not as first char */
static uint8 valid_symchars[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, /* $ . */
2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,1, /* 0-9 ? */
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* A-O */
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* P-Z _ */
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* a-o */
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, /* p-z */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/* table of valid argument characters,
0=invalid, 1=valid, 2=valid, but indicates string */
static uint8 valid_argchars[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,0,1,0,0,2,0,0,0,0,0,0,1,0, /* " $ ' . */
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1, /* 0-9 ? */
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* A-O */
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* P-Z _ */
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* a-o */
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, /* p-z */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/* valid operators */
#define NUMOPS 10
static char valid_operators[NUMOPS] = {
'+','-','*','/','%','<','>','&','|','^'
};
#define MAXOPPRI 5
static uint8 op_priority[NUMOPS] = {
4,4,5,5,5,3,3,2,0,1
};
char *getsymbol(struct GlobalVars *gv,char *s)
/* read a symbol string into gv->strbuf */
{
uint8 *vsc = valid_symchars;
char *b = gv->strbuf;
int bsize = STRBUFSIZE-2;
if (*s == '@') { /* '@' is allowed as first character */
*b++ = *s++;
bsize--;
}
if (vsc[(unsigned char)*s] == 1) { /* first character valid? */
*b++ = *s++;
while (vsc[(unsigned char)*s] && bsize--)
*b++ = *s++;
}
*b = 0;
return (s);
}
char *getarg(struct GlobalVars *gv,char *s)
/* read next argument into gv->strbuf */
{
uint8 v,*vac = valid_argchars;
char c,*b = gv->strbuf;
int bsize = STRBUFSIZE-1;
if (*s == '@') { /* '@' is allowed as first character */
*b++ = *s++;
bsize--;
}
while ((v = vac[(unsigned char)*s]) && bsize--) {
*b++ = *s++;
if (v==2) { /* string? */
c = *(s-1);
for (;;) {
if (bsize--) {
if (!(*b++ = *s)) /* string can only be terminated by EOL */
return (s);
}
else
return (s);
if (*s++ == c) {
if (*s==c || *(s-2)=='\\') {
if (bsize--) /* "", '' \" or \' don't terminate the string */
*b++ = *s++;
else
return (s);
}
else
break;
}
}
}
}
*b = 0;
return (s);
}
char *skipspaces(char *s)
/* advance string pointer to the first character, which is no white space */
{
while (*s==' ' || *s=='\t')
++s;
return (s);
}
char *remquotes(char *s)
/* remove " or ', if present and return new strbuf-pointer */
{
int len;
char c = *s;
if (c=='\"' || c=='\'') /* string is in quotes */
if (len = strlen(++s) - 1)
if (s[len] == c)
s[len] = 0;
return (s);
}
void checkEOL(char *s)
/* check for illegal extra characters on line */
{
s = skipspaces(s);
if (*s && *s!='#') /* only comment is allowed as an extra character */
error(18); /* extra characters on line */
}
char *skipexpression(struct GlobalVars *gv,char *s)
{
char c;
do {
s = getarg(gv,s);
s = skipspaces(s);
c = *s++;
}
while (c!=0 && c!='#' && c!=',');
return (--s);
}
void read_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
struct MacroParams *mp,char *op)
/* read parameters and store pointers to their first character */
{
char c;
mp->param[0] = mp->param0;
if (pl->branch_hint)
mp->param0[0] = pl->branch_hint>0 ? '+